/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Es2pandad.h"
#include "utils/logger.h"

#include <functional>
#include <optional>

namespace panda::es2panda::ls {

Es2pandaLSPServer::Es2pandaLSPServer(Endpoint &ep)
        : ep_(ep)
{
    OnCall("textDocument/Initialize", std::bind(&Es2pandaLSPServer::onInitialize, this, std::placeholders::_1, std::placeholders::_2));
    OnCall("textDocument/completion", std::bind(&Es2pandaLSPServer::onCompletion, this, std::placeholders::_1, std::placeholders::_2));
}

bool Es2pandaLSPServer::Run()
{
        return ep_.Loop(*this);
}

void Es2pandaLSPServer::OnCall(const char *method, MethodHandler &&handler)
{
    os::memory::LockHolder lock(method_handlers_mutex_);
    method_handlers_[method] = std::move(handler);
}

void Es2pandaLSPServer::OnNotify(const char *method, NotifyHandler &&handler)
{
    os::memory::LockHolder lock(method_handlers_mutex_);
    notify_handlers_[method] = std::move(handler);
}

bool Es2pandaLSPServer::onCall(const std::string &method, panda::JsonObject &params, panda::JsonObject::NumT id)
{
    auto handler = method_handlers_.find(method);       
    if (handler != method_handlers_.end()) {
        handler->second(params, [&method, &id, this](std::optional<JsonObjectBuilder> &&result[[maybe_unused]]) {
                LOG(DEBUG,ES2PANDAD) << "reply method: " << method;
                ep_.Reply(id, std::move(result));
        });
    } else {
        LOG(ERROR, ES2PANDAD) << "method not found" << id;
        return false;
    }

    return true;
}

// handlers
void Es2pandaLSPServer::onInitialize(const JsonObject &params [[maybe_unused]],
                                     CallBack &&cb [[maybe_unused]])
{
    LOG(ERROR, ES2PANDAD) << "handler: " << __func__;
}

void Es2pandaLSPServer::onCompletion(const JsonObject &params [[maybe_unused]],
                                     CallBack &&cb)
{
    LOG(ERROR, ES2PANDAD) << "handler: " << __func__;
    JsonObjectBuilder empty;
    cb(std::make_optional(std::move(empty)));
}

}
